package service.cluster
{
    import mx.controls.Alert;
    import mx.rpc.events.FaultEvent;
    import mx.rpc.events.ResultEvent;
    import mx.rpc.remoting.mxml.RemoteObject;

    import common.Config;
    import model.cluster.ClusterDataTable;
    import model.cluster.ClusterDataType;
    import model.cluster.ClusterResult;

    public class ClusterService
    {
        [Bindable]
        public var clusterDataTable:ClusterDataTable;
        [Bindable]
        public var clusterDataType:ClusterDataType;
        [Bindable]
        public var clusterResult:ClusterResult;

        private var remoteObject:RemoteObject;
        private static var _instance:ClusterService;

        public function ClusterService(privateClass:PrivateClass)
        {
            this.remoteObject = new RemoteObject();
            this.remoteObject.destination = "ClusterGateway"
            this.remoteObject.endpoint = Config.serverUrl;
            this.remoteObject.requestTimeout = Config.requestTimeout;
            this.remoteObject.concurrency = Config.concurrency;
            this.remoteObject.showBusyCursor = true;

            this.clusterDataTable = new ClusterDataTable();
            this.clusterDataType = new ClusterDataType();
            this.clusterResult = new ClusterResult();
        }

        public static function getInstance():ClusterService
        {
            if(ClusterService._instance == null)
            {
                ClusterService._instance = new ClusterService(
                                                new PrivateClass());
            }
            return ClusterService._instance;
        }

        public function addListeners(resultFunc:Function,
                                     faultFunc:Function):void
        {
            this.remoteObject.addEventListener(ResultEvent.RESULT,
                                               resultFunc);
            this.remoteObject.addEventListener(FaultEvent.FAULT,
                                               faultFunc);
        }

        public function removeListeners(resultFunc:Function,
                                        faultFunc:Function):void
        {
            this.remoteObject.removeEventListener(ResultEvent.RESULT,
                                                  resultFunc);
            this.remoteObject.removeEventListener(FaultEvent.FAULT,
                                                  faultFunc);
        }

        //--------------------------------------------------------------------
        // TODO: get the data table
        public function getDataTable():void
        {
            this.addListeners(getDataTableResult, getDataTableFault);
            this.remoteObject.getDataTable();
        }

        public function getDataTableResult(event:ResultEvent):void
        {
            this.removeListeners(getDataTableResult, getDataTableFault);
            this.clusterDataTable.update(event.message.body.dataTable);
        }

        public function getDataTableFault(event:FaultEvent):void
        {
            this.removeListeners(getDataTableResult, getDataTableFault);
            Alert.show("Get data table fault");
        }
        //--------------------------------------------------------------------
        // TODO: get the data type
        public function getDataType(id:int):void
        {
            this.addListeners(getDataTypeResult, getDataTypeFault);
            this.remoteObject.getDataType(id);
        }

        public function getDataTypeResult(event:ResultEvent):void
        {
            this.removeListeners(getDataTypeResult, getDataTypeFault);
            this.clusterDataType.update(event.message.body.dataType);
        }

        public function getDataTypeFault(event:FaultEvent):void
        {
            this.removeListeners(getDataTypeResult, getDataTypeFault);
            Alert.show("Get data type fault");
        }
        //--------------------------------------------------------------------
        //TODO:kMeansCluster
        public function kMeansCluster(id:int, enableList:Array, n:int):void
        {
            this.addListeners(kMeansClusterResult, kMeansClusterFault);
            this.remoteObject.kMeansCluster(id, enableList, n);
        }

        public function kMeansClusterResult(event:ResultEvent):void
        {
            this.removeListeners(kMeansClusterResult, kMeansClusterFault);
            this.clusterResult.update(event.message.body.result);
        }

        public function kMeansClusterFault(event:FaultEvent):void
        {
            this.removeListeners(kMeansClusterResult, kMeansClusterFault);
            Alert.show("K means cluster fault");
        }
    }
}

class PrivateClass
{
    public function PrivateClass() {}
}
